
from sqlalchemy import Column, String, Integer
from sqlalchemy.orm import Session

from FastApi import ErrorCode
from FastApi.Common import Error
from FastApi.Database import Base
from FastApi.Model.ApplicationBaseModel import ApplicationBaseModel
from Lib.Utils import Password, GeneratorToken


class UserTokenModel(Base, ApplicationBaseModel):
    __tablename__ = "game_token"
    id = Column(Integer, primary_key=True, index=True)
    user_id = Column(Integer)
    create_time = Column(Integer)
    expire_time = Column(Integer)
    token = Column(String(36))
    device = Column(String(10))

    def GenerateToken(self, user_id: int, device: str, db: Session):
        res_token = db.query(UserTokenModel).filter(
                UserTokenModel.user_id == user_id and device == UserTokenModel.device).first()
        import time
        now_time = int(time.time())
        if res_token:
            expire_time = res_token.expire_time
            if now_time >= expire_time:
                db.query(UserTokenModel).filter(
                        UserTokenModel.user_id == user_id and device == UserTokenModel.device).update({
                        "token"      : GeneratorToken(),
                        "expire_time": self.GenerateExpireTime()
                })
                db.commit()
            return res_token.token
        else:
            token = GeneratorToken()
            token_data = UserTokenModel(
                    user_id=user_id,
                    create_time=now_time,
                    expire_time=self.GenerateExpireTime(),
                    token=token,
                    device=device
            )
            db.add(token_data)
            db.commit()
            db.refresh(token_data)
            return token

    def GenerateExpireTime(self, expire_time=60 * 60 * 12):
        import time
        return int(time.time() + expire_time)

    def GetUserInfo(self, token: str, device: str, db: Session):
        user_id = db.query(UserTokenModel).filter(
                UserTokenModel.token == token and UserTokenModel.device == device).first()['user_id']
        return UserModel().GetUserByUserId(user_id)


class UserModel(Base, ApplicationBaseModel):
    error: Error

    __tablename__ = "game_user"
    id = Column(Integer, primary_key=True, index=True)
    user_name = Column(String(255))
    user_pass = Column(String(255))
    user_nickname = Column(String(255))
    open_id = Column(String(255))
    avatar = Column(String(255))
    gold = Column(Integer)
    carbonic = Column(Integer)
    alloy = Column(Integer)
    ticket = Column(Integer)

    def Add(self, db: Session, user_name: str, user_pass: str):
        if self.GetUserByUserName(db, user_name):
            self.error = Error(ErrorCode.UNIQUE_USER_NAME, "用户名重复")
            return False
        data = UserModel(
                user_name=user_name,
                user_pass=user_pass,
                user_nickname=user_name,
                open_id="",
                avatar="",
                gold=0,
                carbonic=0,
                alloy=0,
                ticket=0,
        )
        db.add(data)
        db.commit()
        db.refresh(data)
        return self.GetUserByUserName(db, data.user_name)

    def GetUserByUserName(self, db: Session, user_name: str):
        return db.query(UserModel).filter(UserModel.user_name == user_name).first()

    def LoginByUserNameAndPwd(self, db: Session, user_name: str, password: str):
        data = db.query(UserModel) \
            .filter(UserModel.user_name == user_name, UserModel.user_pass == Password(password)).first()
        if not data: return None
        return {**{
                "user_id"      : data.id,
                "user_name"    : data.user_name,
                "user_pass"    : data.user_pass,
                "user_nickname": data.user_nickname
        }, **self.GetUserToken(data.id, "app", db)}

    def GetUserToken(self, user_id: int, device: str, db: Session):
        return {"token": UserTokenModel().GenerateToken(user_id, device, db)}

    def GetUserByUserId(self, user_id, db: Session):
        return db.query(UserModel).filter(UserModel.id == user_id).first()
